﻿// ***********************************************************************
// Assembly         : Tinkerc.Framework.Common
// Author           : Tinkerc
// Created          : 09-20-2014
//
// Last Modified By : Tinkerc
// Last Modified On : 09-20-2014
// ***********************************************************************
// <copyright file="ExtensionHelper.cs" company="cry">
//     Copyright (c) cry. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ServiceStack.Text;

/// <summary>
/// The Utility namespace.
/// </summary>
namespace Tinkerc.Framework.Common.Utility
{
    /// <summary>
    /// 扩展方法
    /// </summary>
    public static class ExtensionHelper
    {
        #region string扩展

        /// <summary>
        /// 是否是Int32类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsInt32(this string str)
        {
            int i;
            var flag = Int32.TryParse(str.Trim(), out i);

            return flag;
        }

        /// <summary>
        /// 转换成int类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="defaultValue">默认的返回值</param>
        /// <returns></returns>
        public static int ToInt32(this string str, int defaultValue = 0)
        {
            int result;
            var flag = Int32.TryParse(str.Trim(), out result);

            return flag ? result : defaultValue;
        }

        /// <summary>
        /// 是否是Int32类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsDecimal(this string str)
        {
            decimal result = 0m;

            var flag = decimal.TryParse((str + "").Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成Decimal类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="defaultValue">默认的返回值</param>
        /// <returns></returns>
        public static decimal ToDecimal(this string str, decimal defaultValue = 0m)
        {
            decimal result;

            var flag = decimal.TryParse(str.Trim(), out result);

            return flag ? result : defaultValue;
        }

        /// <summary>
        /// 是否是Int64类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsInt64(this string str)
        {
            Int64 result;

            var flag = Int64.TryParse(str.Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成long类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="defaultValue">默认的返回值</param>
        /// <returns></returns>
        public static long ToInt64(this string str, long defaultValue = 0L)
        {
            Int64 result;
            var flag = Int64.TryParse(str.Trim(), out result);

            return flag ? result : defaultValue;
        }

        /// <summary>
        /// 是否是Double类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsDouble(this string str)
        {
            double result;
            var flag = double.TryParse(str.Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成Double类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="defaultValue">默认的返回值</param>
        /// <returns></returns>
        public static double ToDouble(this string str, double defaultValue = 0d)
        {
            double result;
            var flag = double.TryParse(str.Trim(), out result);

            return flag ? result : defaultValue;
        }

        /// <summary>
        /// 是否是Float类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsFloat(this string str)
        {
            float result;
            var flag = float.TryParse(str.Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成Float类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="defaultValue">默认的返回值</param>
        /// <returns></returns>
        public static float ToFloat(this string str, float defaultValue = 0f)
        {
            float result;
            var flag = float.TryParse(str.Trim(), out result);

            return flag ? result : defaultValue;
        }

        /// <summary>
        /// 是否是Int32类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsDatetime(this string str)
        {
            DateTime result;
            var flag = DateTime.TryParse(str.Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成Datetime类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static DateTime ToDatetime(this string str)
        {
            return Convert.ToDateTime(str);
        }

        /// <summary>
        /// 是否是Int32类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool IsBoolean(this string str)
        {
            bool result;
            var flag = bool.TryParse(str.Trim(), out result);

            return flag;
        }

        /// <summary>
        /// 转换成Boolean类型
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <returns></returns>
        public static bool ToBoolean(this string str)
        {
            bool result;
            return bool.TryParse(str.Trim(), out result);
        }

        public static DateTime ToDateTimeForExcel(this string str)
        {
            double days = str.Trim().ToDouble();
            return "1899-12-30 0:00:00".ToDatetime().AddDays(days);
        }

        public static bool IsUNumber(this string str)
        {
            Regex rg = new Regex(@"^\d+");
            return rg.IsMatch(str);
        }

        /// <summary>
        /// 检测是否是正确的单电子邮箱格式
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns><c>true</c> if the specified string is email; otherwise, <c>false</c>.</returns>
        public static bool IsEmail(this string str)
        {
            //Regex r = new Regex("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$");
            return Regex.IsMatch(str, @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
        }

        /// <summary>
        /// 检测是否是正确的电话号码格式
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns><c>true</c> if the specified string is telephone; otherwise, <c>false</c>.</returns>
        public static bool IsTelephone(this string str)
        {

            return Regex.IsMatch(str, @"^(\d{3,4}[-_－—]{1}\d{5,8})?[-_－—]?\d{1,8}?$");

        }

        /// <summary>
        /// 检测是否是手机号码
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns><c>true</c> if the specified string is mobile; otherwise, <c>false</c>.</returns>
        public static bool IsMobile(this string str)
        {
            //Regex r = new Regex("^(13[0-9]|15[012356789]|18[02356789]|147)\\d{8}$");
            return System.Text.RegularExpressions.Regex.IsMatch(str, @"^(13[0-9]|15[0-9]|14[0-9]|18[0-9])\d{8}$");
        }

        /// <summary>
        /// 是否国内身份证号码位数是否正确
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns><c>true</c> if [is identity card] [the specified string]; otherwise, <c>false</c>.</returns>
        public static bool IsIdentityCard(this string str)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(str, @"^(13[0-9]|15[0|3|6|7|8|9]|18[8|9])\d{8}$");
        }

        /// <summary>
        /// 是否为中文
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="str">验证字符串</param>
        /// <returns><c>true</c> if the specified string is chinese; otherwise, <c>false</c>.</returns>
        public static bool IsChinese(this string str)
        {
            Regex reg = new Regex("^[\u4e00-\u9fa5]$");

            return str.Any(t => reg.IsMatch(t.ToString()));
        }

        #endregion

        #region List扩展
        /// <summary>
        /// List分页拆分成多个List
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">The list.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <returns>List&lt;List&lt;T&gt;&gt;.</returns>
        public static List<List<T>> Paging<T>(this List<T> list, int pageSize)
        {
            var result = new List<List<T>>();
            var totalPage = Math.Ceiling(((decimal)list.Count) / ((decimal)pageSize));
            for (int i = 1; i <= totalPage; i++)
            {
                result.Add(
                    list.Skip((i - 1) * pageSize).Take(pageSize).ToList()
                    );
            }
            return result;
        }

        /// <summary>
        /// Joins the specified values.
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="values">The values.</param>
        /// <param name="seperator">The seperator.</param>
        /// <returns>System.String.</returns>
        public static string Join<T>(this IEnumerable<T> values, string seperator)
        {
            var sb = new StringBuilder();
            foreach (var value in values)
            {
                if (sb.Length > 0)
                    sb.Append(seperator);
                sb.Append(value);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 连接实体泛型里面指定属性的所有值
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="list">实体集合</param>
        /// <param name="propertyName">指定属性</param>
        /// <param name="seperator">分隔符号</param>
        /// <returns>System.String.</returns>
        public static string JoinString<T>(this List<T> list, string propertyName, string seperator)
        {
            List<string> vals = new List<string>();

            foreach (T t in list)
            {
                PropertyInfo[] propertys = t.GetType().GetProperties();

                T t1 = t;
                vals.AddRange(from pi in propertys where pi.Name == propertyName select pi.GetValue(t1, null) into value where value != DBNull.Value select value.ToString());
            }
            string result = string.Join(seperator, vals.ToArray());

            return result;
        }

        /// <summary>
        /// Determines whether [is null or empty] [the specified list].
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">The list.</param>
        /// <returns><c>true</c> if [is null or empty] [the specified list]; otherwise, <c>false</c>.</returns>
        public static bool IsNullOrEmpty<T>(this List<T> list)
        {
            return list == null || list.Count == 0;
        }

        #endregion

        #region 实体对象扩展

        /// <summary>
        /// 得到包含对象所有属性的字符串列表
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns>List&lt;System.String&gt;.</returns>
        public static List<string> GetPropertyList(this object model)
        {
            return model.GetType().GetProperties().Select(t => t.Name).ToList();
        }

        /// <summary>
        /// 连接实体对象的所有属性值
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">The object.</param>
        /// <param name="seperator">The seperator.</param>
        /// <returns>System.String.</returns>
        public static string JoinStringAll<T>(this T obj, string seperator = "")
        {
            PropertyInfo[] propertys = obj.GetType().GetProperties();

            string result = string.Join(seperator, (from pi in propertys select pi.GetValue(obj, null) into value where value != null select value.ToString()).ToArray());

            return result;

        }

        /// <summary>
        /// 复制一个model
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model">The model.</param>
        /// <returns>T.</returns>
        public static T Copy<T>(this T model) where T : class , new()
        {
            var result = new T();
            foreach (var p in model.GetPropertyList())
            {
                result.GetType().GetProperty(p).SetValue(result,
                    model.GetType().GetProperty(p).GetValue(model, null), null);
            }
            return result;
        }


        #endregion

        #region decimal
        /// <summary>
        /// The dx number
        /// </summary>
        private static readonly String[] DxNum = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
        /// <summary>
        /// The dx yuan
        /// </summary>
        private static readonly String[] DxYuan = { "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万" };
        /// <summary>
        /// The dw x
        /// </summary>
        private static readonly String[] DwX = { "角", "分" };

        /// <summary>
        /// 金额小写转中文大写。
        /// 整数支持到万亿；小数部分支持到分(超过两位将进行Banker舍入法处理)
        /// Author:Tinkerc
        /// CreateDate: 2014-09-20 23:32:02
        /// </summary>
        /// <param name="money">需要转换的双精度浮点数</param>
        /// <returns>转换后的字符串</returns>
        public static string ToMoneyString(this decimal money)
        {
            string NumStr;//整个数字字符串
            string NumStr_Zh;//整数部分
            string NumSr_X = "";//小数部分
            string NumStr_DQ;//当前的数字字符
            string NumStr_R = "";//返回的字符串

            money = Math.Round(money, 2);//四舍五入取两位
            //各种非正常情况处理
            if (money < 0)
                return "转换失败";
            else if (money > 9999999999999.99m)
                return "金额过大，无法转换";
            else if (money == 0)
                return DxNum[0] + DxYuan[0];
            else
            {
                NumStr = money.ToString();
                //分开整数与小数处理
                if (NumStr.IndexOf(".") != -1)
                {
                    NumStr_Zh = NumStr.Substring(0, NumStr.IndexOf("."));
                    NumSr_X = NumStr.Substring(NumStr.IndexOf(".") + 1);
                }
                else
                {
                    NumStr_Zh = NumStr;
                }
                //判断是否有整数部分
                if (long.Parse(NumStr_Zh) > 0)
                {
                    long len = NumStr_Zh.Length - 1;
                    //整数部分转换
                    for (int a = 0; a <= len; a++)
                    {
                        NumStr_DQ = NumStr_Zh.Substring(a, 1);
                        if (long.Parse(NumStr_DQ) != 0)
                        {
                            NumStr_R += DxNum[long.Parse(NumStr_DQ)] + DxYuan[len - a];
                        }
                        else
                        {
                            if ((len - a) == 0 || (len - a) == 4 || (len - a) == 8)
                                NumStr_R += DxYuan[len - a];
                            if ((a + 1) <= len)
                            {
                                NumStr_DQ = NumStr_Zh.Substring((a + 1), 1);
                                if (long.Parse(NumStr_DQ) == 0)
                                    continue;
                                else
                                    NumStr_R += DxNum[0];
                            }
                        }
                    }
                }
                //判断是否含有小数部分
                if (NumSr_X != "" && long.Parse(NumSr_X) > 0)
                {
                    //小数部分转换
                    for (int b = 0; b < NumSr_X.Length; b++)
                    {
                        NumStr_DQ = NumSr_X.Substring(b, 1);
                        if (int.Parse(NumStr_DQ) != 0)
                            NumStr_R += DxNum[long.Parse(NumStr_DQ)] + DwX[b];
                        else
                        {
                            if ((b + 1) < NumSr_X.Length)
                            {
                                NumStr_DQ = NumSr_X.Substring((b + 1), 1);
                                if (long.Parse(NumStr_DQ) == 0)
                                    continue;
                            }
                            if (b != (NumSr_X.Length - 1))
                                NumStr_R += DxNum[0];
                        }
                    }
                }
                else
                {
                    NumStr_R += "整";
                }
                return NumStr_R;
            }
        }

        #endregion

        /// <summary>
        /// 设置角标数量大于99的显示99
        /// </summary>
        /// <param name="oldCount"></param>
        /// <returns></returns>
        public static int SetNotifyCount(this int oldCount)
        {
            return oldCount > 99 ? 99 : oldCount;
        }
    }
}
